using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using Common;
using Common.Enum;
using Common.NotifyEvent;
using SExperiment.ExperimentResult;
using SProject;
using SProject.BasicInformation;

namespace SExperiment
{
	[Serializable]
	public class Sample : NotifyPropertyChanged, IComparable
	{
		[NonSerialized]
		private bool _IsSerializePatient = true;

		[NonSerialized]
		private PatientInfo _tempPatientInfo;

		private string _CompoundTubeNo;

		private string _SampleName;

		private ObservableCollection<SampleTargetItem> _Items = new ObservableCollection<SampleTargetItem>();

		private List<Well> _Wells = new List<Well>();

		[NonSerialized]
		private SampleResult _Result;

		public bool IsSerializePatient
		{
			get
			{
				return _IsSerializePatient;
			}
			set
			{
				_IsSerializePatient = value;
			}
		}

		public string CompoundTubeNo
		{
			get
			{
				return _CompoundTubeNo;
			}
			set
			{
				if (!(_CompoundTubeNo == value))
				{
					_CompoundTubeNo = value;
					OnPropertyChanged("CompoundTubeNo");
				}
			}
		}

		public string SampleName
		{
			get
			{
				return _SampleName;
			}
			set
			{
				if (!(_SampleName == value))
				{
					_SampleName = value;
					OnPropertyChanged("SampleName");
				}
			}
		}

		public ObservableCollection<SampleTargetItem> Items
		{
			get
			{
				return _Items;
			}
			set
			{
				if (_Items != value)
				{
					_Items = value;
					OnPropertyChanged("Items");
				}
			}
		}

		public PatientInfo PatientInfo { get; private set; }

		public Project Project { get; set; }

		public List<Well> Wells
		{
			get
			{
				if (_Wells == null)
				{
					_Wells = new List<Well>();
				}
				return _Wells;
			}
		}

		public string WellNames
		{
			get
			{
				StringBuilder stringBuilder = new StringBuilder();
				for (int i = 0; i < Wells.Count; i++)
				{
					if (i > 0)
					{
						stringBuilder.Append(",");
					}
					stringBuilder.Append(Wells[i].CellName);
				}
				return stringBuilder.ToString();
			}
		}

		public SampleResult Result
		{
			get
			{
				if (_Result == null)
				{
					_Result = new SampleResult();
				}
				return _Result;
			}
			set
			{
				if (_Result != value)
				{
					_Result = value;
					OnPropertyChanged("Result");
				}
			}
		}

		[OnSerializing]
		private void OnSerializing(StreamingContext context)
		{
			if (!IsSerializePatient)
			{
				_tempPatientInfo = PatientInfo;
				PatientInfo = new PatientInfo(_tempPatientInfo.CustomData.Count);
			}
		}

		[OnSerialized]
		private void OnSerializd(StreamingContext context)
		{
			if (!IsSerializePatient)
			{
				PatientInfo = _tempPatientInfo;
			}
		}

		private Sample()
		{
			PatientInfo = new PatientInfo(0);
		}

		public Sample(int customCount)
			: this()
		{
			PatientInfo = new PatientInfo(customCount);
		}

		public Sample(Project project, int customCount)
			: this(customCount)
		{
			Project = project;
			if (project != null)
			{
				Target target = project.Target;
				IList<TargetItem> list = (from s in target.Items
					orderby s.ChannelNo
					orderby s.TubeNo
					select s).ToList();
				for (int i = 0; i < list.Count; i++)
				{
					TargetItem targetItem = list[i];
					Items.Add(new SampleTargetItem(project.BasicInfo.Type)
					{
						TubeName = targetItem.TubeName,
						TubeNo = targetItem.TubeNo,
						ChannelNo = targetItem.ChannelNo,
						TargetName = targetItem.Name,
						Dye = targetItem.Dye
					});
				}
			}
		}

		public SampleTargetItem GetTargetItem(string targetName)
		{
			return _Items.Where((SampleTargetItem s) => s.TargetName == targetName).FirstOrDefault();
		}

		public Well GetWell(int no)
		{
			return Wells.Where((Well s) => s.MultiTubeID == no).FirstOrDefault();
		}

		public Sample CreateBasicSample()
		{
			Sample sample = new Sample();
			sample.CompoundTubeNo = CompoundTubeNo;
			sample.SampleName = SampleName;
			sample.Items.Clear();
			for (int i = 0; i < Items.Count; i++)
			{
				sample.Items.Add(new SampleTargetItem(Items[i]));
			}
			return sample;
		}

		public Sample CreateBasicSample2()
		{
			Sample sample = new Sample();
			sample.CompoundTubeNo = CompoundTubeNo;
			sample.SampleName = SampleName;
			sample.PatientInfo.ID = PatientInfo.ID;
			sample.PatientInfo.Remark = PatientInfo.Remark;
			sample.Items.Clear();
			for (int i = 0; i < Items.Count; i++)
			{
				sample.Items.Add(new SampleTargetItem(Items[i]));
			}
			return sample;
		}

		public override bool Equals(object obj)
		{
			if (obj == null || !(obj is Sample))
			{
				return false;
			}
			if (base.Equals(obj))
			{
				return true;
			}
			Sample sample = obj as Sample;
			if (CompoundTubeNo != sample.CompoundTubeNo || Items.Count != sample.Items.Count || Project != sample.Project || WellNames != sample.WellNames)
			{
				return false;
			}
			for (int i = 0; i < Items.Count; i++)
			{
				if (!Items[i].Equals(sample.Items[i]))
				{
					return false;
				}
			}
			return true;
		}

		public override int GetHashCode()
		{
			return base.GetHashCode();
		}

		public void ResetResult()
		{
			Result = new SampleResult();
		}

		public void SaveToStream(StreamEx stream, bool saveRawCurve = false, EPatientInfoSaveType savePatientInfo = EPatientInfoSaveType.None)
		{
			stream.Write(PropertyKey.Key_Sample);
			List<PropertyKey> list = new List<PropertyKey>();
			List<byte[]> list2 = new List<byte[]>();
			StreamEx streamEx;
			if (savePatientInfo != EPatientInfoSaveType.None)
			{
				list.Add(PropertyKey.Key_PatientInfo);
				streamEx = new StreamEx();
				PatientInfo.SaveToStream(streamEx, savePatientInfo);
				list2.Add(streamEx.ToArray());
				streamEx.Close();
			}
			if (!string.IsNullOrEmpty(CompoundTubeNo))
			{
				list.Add(PropertyKey.Key_CompoundTubeNo);
				list2.Add(BytesConverter.GetBytes(CompoundTubeNo));
			}
			if (!string.IsNullOrEmpty(SampleName))
			{
				list.Add(PropertyKey.Key_SampleName);
				list2.Add(BytesConverter.GetBytes(SampleName));
			}
			streamEx = new StreamEx();
			streamEx.Write(Items.Count);
			foreach (SampleTargetItem item in Items)
			{
				item.SaveToStream(streamEx, saveRawCurve);
			}
			list.Add(PropertyKey.Key_Items);
			list2.Add(streamEx.ToArray());
			streamEx.Close();
			list.Add(PropertyKey.Key_SampleResult);
			streamEx = new StreamEx();
			Result.SaveToStream(streamEx);
			list2.Add(streamEx.ToArray());
			streamEx.Close();
			stream.Write(PropertyKey.Key_Index);
			stream.WriteIndex(list, list2);
			stream.Flush();
		}

		public bool ReadFromStream(StreamEx stream)
		{
			PropertyKey propertyKey = stream.ReadKey();
			if (propertyKey == PropertyKey.Key_Sample)
			{
				propertyKey = stream.ReadKey();
				if (propertyKey == PropertyKey.Key_Index)
				{
					List<PropertyKey> keys;
					List<byte[]> dates;
					stream.ReadIndex(out keys, out dates);
					for (int i = 0; i < keys.Count; i++)
					{
						switch (keys[i])
						{
						case PropertyKey.Key_CompoundTubeNo:
							CompoundTubeNo = BytesConverter.BytesToString(dates[i]);
							break;
						case PropertyKey.Key_SampleName:
							SampleName = BytesConverter.BytesToString(dates[i]);
							break;
						case PropertyKey.Key_PatientInfo:
						{
							StreamEx streamEx = new StreamEx();
							streamEx.Write(dates[i]);
							streamEx.Seek(0L, SeekOrigin.Begin);
							PatientInfo.ReadFromStream(streamEx);
							streamEx.Close();
							break;
						}
						case PropertyKey.Key_Items:
						{
							StreamEx streamEx = new StreamEx();
							streamEx.Write(dates[i]);
							streamEx.Seek(0L, SeekOrigin.Begin);
							int num = streamEx.ReadInt();
							for (int j = 0; j < num; j++)
							{
								SampleTargetItem sampleTargetItem = new SampleTargetItem(Project.BasicInfo.Type);
								sampleTargetItem.ReadFromStream(streamEx);
								Items.Add(sampleTargetItem);
							}
							streamEx.Close();
							break;
						}
						case PropertyKey.Key_SampleResult:
						{
							StreamEx streamEx = new StreamEx();
							streamEx.Write(dates[i]);
							streamEx.Seek(0L, SeekOrigin.Begin);
							Result.ReadFromStream(streamEx);
							streamEx.Close();
							break;
						}
						}
					}
					return true;
				}
				stream.Seek(-4L, SeekOrigin.Current);
				while (true)
				{
					switch (stream.ReadKey())
					{
					case PropertyKey.Key_CompoundTubeNo:
						CompoundTubeNo = stream.ReadString();
						break;
					case PropertyKey.Key_PatientInfo:
						PatientInfo.ReadFromStream(stream);
						break;
					case PropertyKey.Key_Item:
					{
						int num2 = stream.ReadInt();
						for (int k = 0; k < num2; k++)
						{
							SampleTargetItem sampleTargetItem2 = new SampleTargetItem(Project.BasicInfo.Type);
							sampleTargetItem2.ReadFromStream(stream);
							Items.Add(sampleTargetItem2);
						}
						break;
					}
					default:
						stream.Seek(-4L, SeekOrigin.Current);
						return true;
					}
				}
			}
			stream.Seek(-4L, SeekOrigin.Current);
			return false;
		}

		public int CompareTo(object obj)
		{
			Sample sample = obj as Sample;
			return Wells[0].ID.CompareTo(sample.Wells[0].ID);
		}
	}
}
